#ifndef DLT645_PROTOCOL_H_
#define DLT645_PROTOCOL_H_

#include <stdbool.h>
#include <stdint.h>
#include "model.h"

/**智能电表相关数据结构*/

#define DLT645_READ_PKG_SIZE (256)
#define DLT645_WRITE_PKG_SIZE (50)

//前导字符
#define PRE_DLT645 (0xfe)
//开始
#define BOF_DLT645 (0x68)
//结束
#define EOF_DLT645 (0x16)
//+-转换
#define DEL_DLT645 (0x33)

#define CODE_RESERVE (0x00)

//1997版功能码
typedef enum {
    V97_READ_DATA = 0x01,
    V97_READ_FOLLOW_DATA = 0x02,
    V97_REREAD_DATA = 0x03,
    V97_WRITE_DATA = 0x04,
    V97_BROADCAST_TIME = 0x08,
    V97_WRITE_ADDR = 0x0a,
    V97_CHANGE_BAUDRATE = 0x0c,
    V97_CHANGE_PSWD = 0x0f,
    V97_CLEAR_DEMAND = 0x10,

    V07_READ_DATA = 0x11,
    V07_READ_FOLLOW_DATA = 0x12,
    V07_READ_ADDR = 0x13,
    V07_WRITE_DATA = 0x14,
    V07_WRITE_ADDR = 0x15,
    V07_BROADCAST_FREEZE = 0x16,
    V07_CHANGE_BAUDRATE = 0x17,
    V07_CHANGE_PSWD = 0x18,
    V07_CLEAR_DEMAND = 0x19,
    V07_CLEAR_METER = 0x1a,
    V07_CLEAR_EVENT = 0x1b,
} dlt645_func_code_e;

typedef struct _control_domain_t {
    dlt645_func_code_e code: 5;
    bool follow: 1;
    bool exception: 1;
    bool direction: 1;
}__attribute__((packed)) control_domain_t;

typedef struct _dlt645_head_t {
    uint8_t bof0;
    uint8_t addr[6];
    uint8_t bof1;
    control_domain_t ctrl_code;
    uint8_t data_len;
}__attribute__((packed)) dlt645_head_t;

typedef struct _dlt645_tail_t {
    uint8_t cs;
    uint8_t eof;
}__attribute__((packed)) dlt645_tail_t;

typedef struct _dlt645_t {
    dlt645_head_t head;
    uint8_t data[DLT645_READ_PKG_SIZE];
    dlt645_tail_t tail;
}__attribute__((packed)) dlt645_t;

dlt645_t *decode_dlt645(const uint8_t *buf, size_t size, dlt645_t *pkg, size_t *nums_read);

int encode_dlt645(uint8_t *buf, size_t size, dlt645_t *pkg);

_Bool create_read_data_req(dlt645_t *pkg, const uint8_t *addr, protocol_e protocol, uint32_t di);

_Bool create_write_data_req(dlt645_t *pkg, const uint8_t *addr, protocol_e protocol, uint32_t di,
                            const uint8_t *data, size_t size);

int dlt645_execute(channel_t *channel, dlt645_t *req, dlt645_t *resp, int timeout);

#endif /* DLT645_PROTOCOL_H_ */
